package com.zty.tool;

import org.slf4j.Logger;
import org.springframework.stereotype.Component;

import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * 封装异步线程池
 * 想象一下你现在去了一家咖啡店点了一杯咖啡。在等待咖啡制作的同时，你不是站在那里发呆，而是可以做一些其他的事情，比如看书或者刷手机。
 * 当咖啡做好了，服务员会告诉你可以取咖啡了。在这个例子中，咖啡的制作就是一个异步过程，而你的其他活动就是在这个异步过程中可以并行处理的任务。
 * <p>
 * 在Java中，Future就像是咖啡店给你的那个取号码牌。
 * 当你提交一个任务给线程池执行时，线程池会立即返回一个Future对象给你。
 * 这个Future对象就是一个承诺，表示线程池会在未来的某个时刻完成这个任务。
 * 与此同时，你拿着这个Future对象可以继续做其他的事情，不必阻塞等待任务完成。
 * <p>
 * Future的作用主要包括：
 * <p>
 * 异步执行：允许你异步执行一个任务，不需要等待任务完成就可以继续执行后续代码。
 * 结果获取：可以在任何需要的时候通过Future对象来获取异步任务的结果。
 * 任务状态检查：可以检查异步任务是否已经完成，或者是否被取消。
 * 超时处理：可以设置超时时间，在指定的时间内如果任务未完成，可以做出相应的处理。
 * Future通常用于以下开发场景：
 * <p>
 * 并发编程：在需要处理多个并发任务，并且这些任务之间相互独立时，可以使用Future来管理这些任务。
 * 非阻塞IO操作：当进行网络请求或文件读写等IO操作时，这些操作可以异步执行，提高程序的响应性能。
 * 复杂计算：对于一些耗时的计算任务，可以放到后台线程中执行，前台线程可以继续处理用户交互。
 * 微服务调用：在微服务架构中，服务之间的调用可以异步进行，提高系统的吞吐量和并发能力。
 * <p>
 * 例如，你正在开发一个网站，需要在用户请求页面时从数据库加载大量数据。如果直接同步加载，用户可能需要等待很长时间。
 * 这时候，你可以启动一个异步任务去加载数据，并立即返回一个加载中的页面给用户。
 * 当异步任务完成后，你可以使用Future对象获取结果，并更新页面内容。
 * <p>
 * 总之，Future提供了一种优雅的方式来处理Java中的异步操作，让程序可以充分利用系统资源，同时提高用户体验和系统性能。
 *
 * @author: zty
 * @date: 2023/1/15
 */
public class CompletableFutureUtils {


    /**
     * 从一个Future对象中获取结果。方法的签名表明它可以用于任何类型T的Future
     *
     * @param future
     * @param timeout
     * @param timeUnit
     * @param defaultValue
     * @param logger       logger的使用是为了确保在Future获取结果时出现的任何异常都可以被记录下来。
     *                     如果不记录这些异常，那么在异步操作失败时，可能会很难找到失败的原因，尤其是在复杂的系统或生产环境中。
     *                     此外，记录将返回默认值的决定也是一种好的实践，因为它提供了一个明确的指示，
     *                     说明方法没有按预期返回结果，而是返回了一个预设的默认值。
     *                     这可以帮助开发人员了解系统何时未能按预期工作，并采取相应的措施。
     * @param <T>
     * @return
     */
    // 定义了一个泛型方法，该方法接受一个Future<T>对象，一个超时值，一个时间单位，一个默认值，以及一个Logger对象。
    public static <T> T getResult(Future<T> future,
                                  long timeout,
                                  TimeUnit timeUnit,
                                  T defaultValue,
                                  Logger logger) {
        try {
            // 尝试从Future对象中获取结果。如果在指定的超时时间内任务完成，它将返回任务的结果。
            return future.get(timeout, timeUnit);
        } catch (Exception e) {
            // 如果在尝试获取结果时出现任何异常（例如超时、中断、执行异常等），则会捕获异常。
            // 使用logger对象记录错误信息。这里记录的是异常的信息和默认值。
            logger.error("com.zty.tool.CompletableFutureUtils.getResult.error:{},defaultValue:{}",
                    e.getMessage(),
                    defaultValue);

            // 再次使用logger对象记录一条错误信息，表明将返回默认值。
            logger.error("com.zty.tool.CompletableFutureUtils.getResult.error.returnDefaultValue:{}", defaultValue);

            // 由于发生了异常，无法获取Future的结果，因此返回传入的默认值。
            return defaultValue;
        }
    }


}
